import {createRouter, createWebHashHistory, createWebHistory, RouteRecordRaw} from "vue-router";
import {ElNotification} from "element-plus";
import NProgress from "nprogress";
import "nprogress/nprogress.css";
import staticRoutes from "./static";
import store from "@/store";
import {service, env} from "@/utils";

NProgress.configure({showSpinner: false});

interface Breadcrumb {
    id: string;
    icon: string;
    path: string;
    title: string;
}

const {HOME_PATH, CONTEXT_PATH, APP_NAME} = env;

// 白名单列表
const whiteList = ["/login", "/register", "/password"];

//基础路由
const routes: DynamicRouteRecordRaw[] = [{
    path: "/login",
    name: "Login",
    component: () => import("@/views/login/index.vue"),
    meta: {
        title: "登录",
    },
}, {
    path: "/register",
    name: "Register",
    component: () => import("@/views/login/components/register-form.vue"),
    meta: {
        title: "注册",
    },
}, {
    path: '/zookeeper',
    name: 'Zookeeper',
    component: () => import('../views/zookeeper/index.vue'),
    meta: {
        title: 'Zookeeper'
    }
}, {
    path: '/hadoop',
    name: 'Hadoop',
    component: () => import('../views/hadoop/index.vue'),
    meta: {
        title: 'Hadoop'
    }
}, {
    path: '/sftp',
    name: 'FileZilla',
    component: () => import('../views/file-zilla/index.vue'),
    meta: {
        title: 'FileZilla'
    }
}, {
    path: "/password",
    name: "ResetPassword",
    component: () => import("@/views/login/components/reset-form.vue"),
    meta: {
        title: "重置密码",
    },
}];

//错误路由
const errorRoutes = {
    path: "/:pathMatch(.*)*",
    hidden: true,
    component: () => import("@/layout/other/404.vue"),
};

// history模式/hash模式
const history = CONTEXT_PATH? createWebHistory(CONTEXT_PATH):createWebHashHistory();

// 构建路由
const router = createRouter({
    history: history,
    routes: routes,
    loaded: false, // 标记动态路由已初始化，防止重复加载
} as AppRouterOptions);

//设置标题
document.title = APP_NAME;

// 路由跳转前
router.beforeEach(async (to, from, next) => {
    NProgress.start();

    //动态标题
    document.title = to.meta.title? `${to.meta.title} - ${APP_NAME}` : `${APP_NAME}`;
    // 如果token已存在
    if (store.userStore.token) {
        let options = router.options as AppRouterOptions;
        if ((to.path === "/" || to.path === "/login")) {
            next("/home");
        } else {
            if (!options.loaded) {
                options.loaded = true;

                // 添加动态路由
                await initDynamicRoute(store.userStore.user, (dynamicRoute: RouteRecordRaw) => router.addRoute(dynamicRoute));

                // 添加错误路由
                router.addRoute(errorRoutes);

                // //整页路由处理
                if (to.meta.fullpage) {
                    to.matched = [to.matched[to.matched.length - 1]];
                }
                next({path: to.path, query: to.query});
            } else {
                next();
            }
        }
    } else {
        // 没有token的情况下，可以进入白名单
        if (whiteList.indexOf(to.path) > -1) {
            next();
        } else {
            next({path: "/login"});
        }
    }
});

// 路由跳转后
router.afterEach((to: any, from: any) => {
    NProgress.done();
});

// 路由跳转错误
router.onError((error) => {
    NProgress.done();
    ElNotification.error({
        title: "路由错误",
        message: error.message,
    });
});

// 参数2： 是否直接将所有模块引入 ，eager：true 表示全部导入
const modules = import.meta.glob('@/views/**/index.vue', {import: 'default', eager: true})

/**
 * 初始化动态路由
 */
async function initDynamicRoute (info: any, addRoute: (dynamicRoute: RouteRecordRaw) => void) {
    await service.get(`/menu/${info.username}`).then(({code, data}) => {
        if (code === 200) {
            const {menus, buttons} = data;
            const routes = generateRoutes([...staticRoutes, ...menus]) as RouteRecordRaw[];
            // 扁平化菜单数据同时初始化页面路径Breadcrumb
            const affix: any[] = [], cache: string[] = [], applets: any[] = [];
            toRouteFlatten(routes).forEach(({path, name, meta}) => {
                if (meta.type === '2') {
                    const {id, title, icon} = meta;
                    applets.push({id, title, icon, path: path, name: name})
                }

                if (meta.affix) {
                    affix.push({path, name, meta});
                }

                if (meta.cache) {
                    cache.push(name);
                }
            })
            // 缓存数据
            store.userStore.setMenu(routes);
            store.userStore.setButtons(buttons);
            store.userStore.setApplets(applets);
            store.userStore.setAffixTabs(affix);
            store.userStore.setCacheRoutes(cache);

            // 构建动态路由
            const dynamicRoute: RouteRecordRaw = {
                path: "/",
                name: "Layout",
                component: () => import("@/layout/index.vue"),
                redirect: HOME_PATH,
                children: [...routes]
            }
            addRoute(dynamicRoute);
        } else {
            console.error("获取菜单失败");
        }
    });
}

/**
 * 根据菜单列表，生成路由数据
 * @param menus  菜单数据源
 */
function generateRoutes(menus: any[]): DynamicRouteRecordRaw[]{
    const treeData: DynamicRouteRecordRaw[] = [];
    menus.forEach(menu => {
        const route: DynamicRouteRecordRaw = getDynamicComponent(menu);
        // 有子菜单的情况，继续递归循环
        if (menu.children?.length > 0) {
            route.children?.push(...generateRoutes(menu.children));
        }
        treeData.push(route);
    });
    return treeData;
}

/**
 * 根据路径，动态获取vue组件
 * @param menu
 */
function getDynamicComponent(menu: any): DynamicRouteRecordRaw {
    let route: DynamicRouteRecordRaw = {
        path: menu.path,
        name: menu.name || menu.path.toCamelCase(),
        component: menu.component,
        children: [],
        meta: menu.meta? menu.meta:{
            id: menu.id,                            //唯一标识
            icon: menu.icon,                        //页面图标
            type: menu.type,                        //菜单，应用
            title: menu.title || '',                //页面标题
            cache: menu.cache || false,             //页面是否缓存
            affix: menu.affix || false,             //页面是否固定
            iframeLink: menu.iframeLink || null,    //内嵌页面URL链接地址
            breadcrumb: [],                         //导航路径
        },
    };

    if (typeof route.component === 'string') {
        if (route.component.indexOf('http') === 0) {
            route.meta.iframeLink = route.component;
            route.component = () => import('@/layout/common/IframeView.vue');
        } else {
            if (route.component && route.component !== 'PageView') {
                route.component = modules[`/src/views${route.component}/index.vue`];
                if (!route.component) {
                    route.component = () => import('@/layout/other/404.vue');
                } else if (route.component?.name){
                    route.name = route.component.name;
                }
            } else {
                route.component = null;
            }
        }
    }
    return route;
}

/**
 * 获取扁平化路由，将多级路由转换成一级路由
 * @param routes 路由菜单
 * @param breadcrumb 所有路由记录
 */
function toRouteFlatten(routes: any[], breadcrumb: Breadcrumb[] = []): any[] {
    return routes.reduce((result, item) => {
        breadcrumb.push({id: item.meta?.id, path: item.path, title: item.meta?.title, icon: item.meta?.icon});
        let arr = Array.isArray(item.children) ? toRouteFlatten(item.children, breadcrumb) : [];
        item.meta.breadcrumb.push(...breadcrumb);
        breadcrumb.pop();
        return result.concat(item, arr);
    }, [])
}

export default router;
